require "http"
require "misc"
require "config"
require "tool"
module(..., package.seeall)

local HW_TOKEN = ""

local function devNotInList(list, dev_name)
    for i, v in ipairs(list) do
        if list[i].device_id == dev_name then
            return false
        end
    end

    return true
end

local function httpRequestFormData(method, url, cert, formData, timeout, cbFnc,
                                   rcvFileName)
    local boundary, body = "--------------------------" .. os.time() ..
            rtos.tick(), {}
    for k, v in pairs(formData) do
        if k == "texts" then
            local bodyText = ""
            for kk, vv in pairs(v) do
                bodyText = bodyText .. "--" .. boundary ..
                        "\r\nContent-Disposition: form-data; name=\"" ..
                        kk .. "\"\r\n\r\n" .. vv .. "\r\n"
            end
            body[#body + 1] = bodyText
        elseif k == "files" then
            local contentType = {
                jpg = "image/jpeg",
                jpeg = "image/jpeg",
                png = "image/png"
            }
            for kk, vv in pairs(v) do
                print(kk, vv)

                body[#body + 1] = "--" .. boundary ..
                        "\r\nContent-Disposition: form-data; name=\"" ..
                        kk .. "\"; filename=\"" ..
                        vv:match("([^/]+)$") ..
                        "\"\r\nContent-Type: " ..
                        (contentType[vv:match("%.(%w+)$")] or
                                "application/octet-stream") ..
                        "\r\n\r\n"
                body[#body + 1] = { file = vv }
                body[#body + 1] = "\r\n"
            end
        end
    end

    body[#body + 1] = "--" .. boundary .. "--\r\n"

    http.request(method, url, cert, {
        ["Content-Type"] = "multipart/form-data; boundary=" .. boundary,
        ["Connection"] = "keep-alive"
    }, body, timeout, cbFnc, rcvFileName)
end

-- http网关注册回复回调函数
local function register_cbFnc(result, prompt, head, body)
    log.info("testHttp.cbFnc", result, prompt)
    if result and head then
        for k, v in pairs(head) do
            log.info("testHttp.cbFnc", k .. ": " .. v)
        end
    end
    if result and body then
        log.info("testHttp.cbFnc", "bodyLen=" .. body:len())
        log.info("testHttp.cbFnc", "body=" .. body)
        local body_json, re, err = json.decode(body)
        if re then
            if body_json["success"] == true then
                nvm.set("ALI_DEVICE_SECRET", body_json["result"]["deviceSecret"])
                nvm.set("ALI_DEVICE_IOTID", body_json["result"]["iotId"])
                sys.publish("ALI_REGISTER")
                log.info("GET SECRET:", body_json["result"]["deviceSecret"],
                        body_json["result"]["iotId"])
            end
        end
    end
end

-- http拓扑关系回复回调函数
local function topo_cbFnc(result, prompt, head, body)
    log.info("testHttp.cbFnc", result, prompt)
    if result and head then
        for k, v in pairs(head) do
            log.info("testHttp.cbFnc", k .. ": " .. v)
        end
    end
    if result and body then
        log.info("testHttp.cbFnc", "bodyLen=" .. body:len())
        log.info("testHttp.cbFnc", "body=" .. body)
        local body_json, re, err = json.decode(body)
        if re then
            if body_json["success"] == true then
                local temp_list = tool.deepCopy(nvm.get("CLEAN_DEV_LIST"))
                for i, v in ipairs(body_json["result"]) do
                    log.info("ID:", v["deviceName"])
                    log.info("SECRET:", v["deviceSecret"])
                    log.info("NAME:", v["nickname"], type(v["nickname"]),
                            string.len(tostring(v["nickname"])))
                    --  判断拓扑子设备本地是否有保存
                    for ii, vv in ipairs(temp_list) do
                        if devNotInList(temp_list, v["deviceName"]) then
                            log.info("NOT IN ID:", v["deviceName"])
                            for iii, vvv in ipairs(temp_list) do
                                if temp_list[iii].device_id == "" then
                                    temp_list[iii].device_id = v["deviceName"]
                                    temp_list[iii].secret = v["deviceSecret"]
                                    if type(v["nickname"]) == "string" then
                                        temp_list[iii].pos = tostring(
                                                v["nickname"])
                                    else
                                        temp_list[iii].pos = "前端" .. iii
                                    end

                                    break
                                end
                            end
                            break
                        end
                    end
                end

                nvm.set("DEV_LIST", temp_list)

                sys.publish("TOPO_UPDATE")
            end
        end
    end
end

-- 调用linkfarm接口注册阿里设备
function http_register()
    -- aLiRegister()
    local deviceName = "GWEV_" .. misc.getImei()
    local productKey = config.ALI_PRODUCTKEY
    local accessID = config.ACCESS_ID
    local accessSecret = config.ACCESS_SECRET
    while tonumber(tool.miscTime()) < 1680248427 do
        sys.wait(1000)
    end
    local timeStamp = tool.miscTime() .. "000"

    local sign_list = { deviceName, productKey, timeStamp, accessSecret }

    table.sort(sign_list) -- 数组排序

    local sign_str = table.concat(sign_list)
    log.info("SIGN__________", sign_str)

    local sign_md5 = string.lower(crypto.md5(sign_str, string.len(sign_str)))

    log.info("SIGN__________", sign_md5)

    httpRequestFormData("POST",
            "https://farm-api.linkta.cn/linkfarm/iot/api/registerDevice",
            nil, {
                texts = {
                    ["deviceName"] = deviceName,
                    ["productKey"] = productKey,
                    ["accessID"] = accessID,
                    ["timestamp"] = timeStamp,
                    ["sign"] = sign_md5
                }
            }, 6000, register_cbFnc)
end

-- 阿里获取网关拓扑关系
function http_topo()
    if nvm.get("ALI_DEVICE_SECRET") ~= "" and nvm.get("ALI_DEVICE_IOTID") then
        local iotID = nvm.get("ALI_DEVICE_IOTID")
        local accessID = config.ACCESS_ID
        local accessSecret = config.ACCESS_SECRET
        local timeStamp = tool.miscTime() .. "000"

        local sign_list = { iotID, accessSecret, timeStamp }
        table.sort(sign_list) -- 数组排序
        local sign_str = table.concat(sign_list)
        local sign_md5 = string.lower(crypto.md5(sign_str, string.len(sign_str)))

        httpRequestFormData("POST",
                "https://farm-api.linkta.cn/linkfarm/iot/api/getThingTopo",
                nil, {
                    texts = {
                        ["iotId"] = iotID,
                        ["accessID"] = accessID,
                        ["timestamp"] = timeStamp,
                        ["sign"] = sign_md5
                    }
                }, 6000, topo_cbFnc)

    end
end

-- http网关注册回复回调函数
local function ys_register_cbFnc(result, prompt, head, body)
    log.info("testHttp.cbFnc", result, prompt)
    if result and head then
        for k, v in pairs(head) do
            log.info("testHttp.cbFnc", k .. ": " .. v)
        end
    end
    if result and body then
        log.info("testHttp.cbFnc", "bodyLen=" .. body:len())
        log.info("testHttp.cbFnc", "body=" .. body)
        local body_json, re, err = json.decode(body)
        if re then
            if body_json["success"] == true then
                nvm.set("YALI_DEVICE_SECRET",
                        body_json["result"]["deviceSecret"])
                nvm.set("YALI_DEVICE_IOTID", body_json["result"]["iotId"])
                sys.publish("YALI_REGISTER")
                log.info("GET SECRET:", body_json["result"]["deviceSecret"],
                        body_json["result"]["iotId"])
            end
        end
    end
end

-- http拓扑关系回复回调函数
local function ys_topo_cbFnc(result, prompt, head, body)
    log.info("testHttp.cbFnc", result, prompt)
    if result and head then
        for k, v in pairs(head) do
            log.info("testHttp.cbFnc", k .. ": " .. v)
        end
    end
    if result and body then
        log.info("testHttp.cbFnc", "bodyLen=" .. body:len())
        log.info("testHttp.cbFnc", "body=" .. body)
        local body_json, re, err = json.decode(body)
        if re then
            if body_json["success"] == true then
                local temp_list = tool.deepCopy(nvm.get("CLEAN_DEV_LIST"))
                for i, v in ipairs(body_json["result"]) do
                    log.info("ID:", v["deviceName"])
                    log.info("SECRET:", v["deviceSecret"])
                    log.info("NAME:", v["nickname"], type(v["nickname"]),
                            string.len(tostring(v["nickname"])))
                    --  判断拓扑子设备本地是否有保存
                    for ii, vv in ipairs(temp_list) do
                        if devNotInList(temp_list, v["deviceName"]) then
                            log.info("NOT IN ID:", v["deviceName"])
                            for iii, vvv in ipairs(temp_list) do
                                if temp_list[iii].device_id == "" then
                                    temp_list[iii].device_id = v["deviceName"]
                                    temp_list[iii].secret = v["deviceSecret"]
                                    if type(v["nickname"]) == "string" then
                                        temp_list[iii].pos = tostring(
                                                v["nickname"])
                                    else
                                        temp_list[iii].pos = "前端" .. iii
                                    end

                                    break
                                end
                            end
                            break
                        end
                    end
                end

                nvm.set("DEV_LIST", temp_list)

                sys.publish("TOPO_UPDATE")
            end
        end
    end
end

function ys_http_register()
    -- aLiRegister()
    local deviceName = 'GWYX_' .. misc.getImei()
    local productKey = config.YALI_PRODUCTKEY
    local accessID = config.ACCESS_ID
    local accessSecret = config.ACCESS_SECRET
    local timeStamp = tool.miscTime() .. "000"

    local sign_list = { deviceName, productKey, timeStamp, accessSecret }

    table.sort(sign_list) -- 数组排序

    local sign_str = table.concat(sign_list)
    log.info("SIGN__________", sign_str)

    local sign_md5 = string.lower(crypto.md5(sign_str, string.len(sign_str)))

    log.info("SIGN__________", sign_md5)

    httpRequestFormData("POST",
            "https://farm-api.linkta.cn/linkfarm/iot/api/registerDevice",
            nil, {
                texts = {
                    ["deviceName"] = deviceName,
                    ["productKey"] = productKey,
                    ["accessID"] = accessID,
                    ["timestamp"] = timeStamp,
                    ["sign"] = sign_md5
                }
            }, 6000, ys_register_cbFnc)
end

function ys_http_topo()
    if nvm.get("YALI_DEVICE_SECRET") ~= "" and nvm.get("YALI_DEVICE_IOTID") then
        local iotID = nvm.get("YALI_DEVICE_IOTID")
        local accessID = config.ACCESS_ID
        local accessSecret = config.ACCESS_SECRET
        local timeStamp = tool.miscTime() .. "000"

        local sign_list = { iotID, accessSecret, timeStamp }
        table.sort(sign_list) -- 数组排序
        local sign_str = table.concat(sign_list)
        local sign_md5 = string.lower(crypto.md5(sign_str, string.len(sign_str)))

        httpRequestFormData("POST",
                "https://farm-api.linkta.cn/linkfarm/iot/api/getThingTopo",
                nil, {
                    texts = {
                        ["iotId"] = iotID,
                        ["accessID"] = accessID,
                        ["timestamp"] = timeStamp,
                        ["sign"] = sign_md5
                    }
                }, 6000, ys_topo_cbFnc)

    end
end

-- 阿里云注册设备
--function aLiRegister()
--    local clk = os.date("*t") -- 获取UTC时间的table
--    local timeStr = string.format("%02d-%02d-%02dT%02d:%02d:%02dZ", clk.year,
--            clk.month, clk.day, clk.hour, clk.min, clk.sec) -- 时间戳
--
--    local url = "Action=RegisterDevice&ProductKey=" .. config.ALI_PRODUCTKEY ..
--            "&DeviceName=" .. "GMRD_" .. misc.getImei() ..
--            "&Version=2018-01-20" .. "&SignatureMethod=HMAC-SHA1" ..
--            "&SignatureVersion=1.0" .. "&RegionId=cn-shenzhen" ..
--            "&SignatureNonce=" .. tool.miscTime() .. "&AccessKeyId=" ..
--            config.ALI_ACCESS_ID .. "&Timestamp=" .. timeStr
--    local url_arr = tool.Split(url, "&")
--    table.sort(url_arr)
--    for i, j in ipairs(url_arr) do
--        log.info("ARR:", j)
--    end
--
--    url = table.concat(url_arr, "&")
--    log.info("ARR_STR", url)
--    local url_utf8 = string.gsub(url, "=", "%%3D")
--    url_utf8 = string.gsub(url_utf8, "&", "%%26")
--    url_utf8 = string.gsub(url_utf8, ":", "%%253A")
--
--    url_utf8 = "GET&%2F&" .. url_utf8
--
--    log.info("ARR_STR", url_utf8)
--
--    local test_url = "GET&%2F&AccessKeyId%3Dtestid%26Action%3DPub%26Format%3DXML%26MessageContent%3DaGVsbG8gd29ybGQ%26ProductKey%3D12345abcde%26Qos%3D0%26RegionId%3Dcn-shanghai%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf%26SignatureVersion%3D1.0%26Timestamp%3D2018-07-31T07%253A43%253A57Z%26TopicFullName%3D%252F12345abcde%252Ftestdevice%252Fuser%252Fget%26Version%3D2018-01-20"
--    local test_secret = "testsecret&"
--    local sha1 = crypto.hmac_sha1(test_url, #test_url, test_secret, #test_secret)
--                       .degist()
--    log.info("BASE 64", crypto.base64_encode(sha1, #sha1))
--end

-- 华为获取token回调函数
local function hwToken_cbFnc(result, prompt, head, body)
    log.info("HW.cbFnc", result, prompt)
    log.info("HW.cbFnc", config.HW_TOKEN_URL .. "/v3/auth/tokens")
    if result and head then
        for k, v in pairs(head) do
            if k == "X-Subject-Token" then
                log.info("GET_TOKEN", v)
                nvm.set("HW_TOKEN", v)
                sys.publish("HW_GETTOKEN")
            end
        end
    end
end

-- 华为注册设备回调函数
local function hwRegister_cbFnc(result, prompt, head, body)
    log.info("HW.cbFnc", result, prompt)
    log.info("HW.cbFnc", config.HW_DEVICE_URL .. "/v5/iot/" ..
            config.HW_PROJECTID .. "/devices")
    if result and head then
        for k, v in pairs(head) do
            log.info("HW_REG", k, v)
        end
        log.info("HW_BODY", body)
        nvm.set("HW_REGISTER", 1)
        sys.publish("HW_REGISTER")
    end
end

-- 华为删除设备回调函数
local function hwDelete_cbFnc(result, prompt, head, body)
    log.info("HW.cbFnc", result, prompt)
    if result then
        log.info("HW DELETE SUS!")
        sys.publish("HW_DELETE")
    end
end

-- 华为获取接口token
function hw_http_getToken()
    log.info("HW GET TOKEN")
    local data = {}
    data["auth"] = {}
    data["auth"]["identity"] = {}
    data["auth"]["identity"]["methods"] = { {} }
    data["auth"]["identity"]["methods"][1] = "password"
    data["auth"]["identity"]["password"] = {}
    data["auth"]["identity"]["password"]["user"] = {}
    data["auth"]["identity"]["password"]["user"]["name"] = config.HW_IOT_USER
    data["auth"]["identity"]["password"]["user"]["password"] = config.HW_IOT_PASSWORD
    data["auth"]["identity"]["password"]["user"]["domain"] = {}
    data["auth"]["identity"]["password"]["user"]["domain"]["name"] = "xxzx"

    local jsonstr = json.encode(data)
    -- log.info("HW_TOKEN", jsonstr)

    http.request("POST", config.HW_TOKEN_URL .. "/v3/auth/tokens", nil,
            { ["Content-Type"] = "application/json" }, jsonstr, 6000,
            hwToken_cbFnc, nil)
end

-- 华为注册设备
function hw_http_register()
    local data = {}
    data["node_id"] = "GWEV_" .. misc.getImei()
    data["device_name"] = "GWEV_" .. misc.getImei()
    -- data["device_id"] = config.HW_DEV_PRODUCTID .. "_GWWL_" .. misc.getImei()
    data["project_id"] = config.HW_PROJECTID
    data["product_id"] = config.HW_DEV_PRODUCTID
    data["app_id"] = config.HW_APPID
    data["auth_info"] = {}
    data["auth_info"]["auth_type"] = "SECRET"
    data["auth_info"]["secret"] = config.HW_SECRET
    data["auth_info"]["secure_access"] = false

    local jsonstr = json.encode(data)
    -- log.info("HW_GEGISTER", jsonstr)
    -- log.info("REGE_TOKEN", nvm.get("HW_TOKEN"))
    http.request("POST", config.HW_DEVICE_URL .. "/v5/iot/" ..
            config.HW_PROJECTID .. "/devices", nil, {
        ["Content-Type"] = "application/json",
        ["X-Auth-Token"] = nvm.get("HW_TOKEN")
    }, jsonstr, 6000, hwRegister_cbFnc, nil)
end

-- 华为删除设备
function hw_http_delete()
    -- log.info("HW_GEGISTER", jsonstr)
    -- log.info("REGE_TOKEN", nvm.get("HW_TOKEN"))
    http.request("POST",
            config.HW_DEVICE_URL .. "/v5/iot/" .. config.HW_PROJECTID ..
                    "/devices/" .. config.HW_DEV_PRODUCTID .. "_GWWL_" ..
                    misc.getImei(), nil, {
                ["Content-Type"] = "application/json",
                ["X-Auth-Token"] = nvm.get("HW_TOKEN")
            }, "", 6000, hwDelete_cbFnc, nil)
end

local function getSim1_cbFnc(result, prompt, head, body)
    log.info("sim1.cbFnc", result, prompt)
    if result and head then
        log.info("sim1_BODY", body)
        local body_json, re, err = json.decode(body)
        if body_json["code"] == "0" then
            nvm.set("SIM_STATE", "true")
            if body_json["data"]["iratePlanName"] ~= nil then
                nvm.set("SIM_PLAN", body_json["data"]["iratePlanName"])
            end

            if body_json["data"]["lastSyncDate"] ~= nil then
                nvm.set("SIM_TIME", body_json["data"]["lastSyncDate"])
            else
                nvm.set("SIM_TIME", "---")
            end

            if body_json["data"]["deviceStatus"] ~= nil then
                if body_json["data"]["deviceStatus"] == "INVENTORY_NAME" then
                    nvm.set("SIM_STATUS", "库存")
                elseif body_json["data"]["deviceStatus"] == "ACTIVATION_READY_NAME" then
                    nvm.set("SIM_STATUS", "可激活")
                elseif body_json["data"]["deviceStatus"] == "ACTIVATED_NAME" then
                    nvm.set("SIM_STATUS", "已激活")
                elseif body_json["data"]["deviceStatus"] == "DEACTIVATED_NAME" then
                    nvm.set("SIM_STATUS", "已停卡")
                elseif body_json["data"]["deviceStatus"] == "RETIRED_NAME" then
                    nvm.set("SIM_STATUS", "已销卡")
                end
            end

            if body_json["data"]["dataUsage"] ~= nil then
                nvm.set("SIM_USE_DATA", body_json["data"]["dataUsage"])
                nvm.set("SIM_LAST_DATA", body_json["data"]["totalDataVolume"] - body_json["data"]["dataUsage"])
            end

        end
    end
end

local function urlencodeTab(params)
    local msg = {}
    for k, v in pairs(params) do
        table.insert(msg, string.urlEncode(k) .. '=' .. string.urlEncode(v))
        table.insert(msg, '&')
    end
    table.remove(msg)
    return table.concat(msg)
end

function getSim1()
    local app_id = "102420198058"
    local app_secret = "b0ea9852b6cb5742d3acbf353f445842"
    local uar = "https://api.simboss.com/2.0/device/detail"
    local iccid = sim.getIccid()
    --local iccid = "89860816262390000225"
    local timeStamp = tool.miscTime() .. "000"
    local sign_str = "appid=" .. app_id .. "&iccid=" .. iccid .. "&timestamp=" .. timeStamp .. app_secret
    local sign = string.lower(crypto.sha256(sign_str))
    local body = "appid=" .. app_id .. "&iccid=" .. iccid .. "&timestamp=" .. timeStamp .. "&sign=" .. sign
    log.info("SIM SIGN", sign_str, sign)
    http.request("POST", uar, nil, {
        ["Content-Type"] = "application/x-www-form-urlencoded"
    }, urlencodeTab({
        appid = app_id,
        timestamp = timeStamp,
        sign = sign,
        iccid = iccid
    }), 6000, getSim1_cbFnc, nil)
end
